package work.mediway.mdm.biz.service.common;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.gson.Gson;
import com.mediway.hos.app.base.seure.util.SecurityUtils;
import com.mediway.hos.base.model.BaseResponse;
import com.mediway.hos.common.utils.ExceptionUtil;
import com.mediway.hos.messgateway.model.entity.MessageEntity;
import com.mediway.hos.messgateway.model.entity.MessageType;
import com.mediway.hos.messgateway.service.MessageTypeService;

import org.json.XML;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.sql.SQLException;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

import javax.sql.DataSource;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.handler.NumberHandler;
import cn.hutool.db.sql.SqlBuilder;
import cn.hutool.db.sql.SqlExecutor;
import cn.hutool.db.sql.Wrapper;
import cn.hutool.http.ContentType;
import cn.hutool.http.Method;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import work.mediway.mdm.biz.bo.DictPushBO;
import work.mediway.mdm.biz.dto.dict.DictDTO;
import work.mediway.mdm.biz.dto.dict.DictDetailDTO;
import work.mediway.mdm.biz.dto.dict.DictFieldDTO;
import work.mediway.mdm.biz.dto.dict.DictGeneralDTO;
import work.mediway.mdm.biz.dto.dict.DictGeneralDeleteDTO;
import work.mediway.mdm.biz.dto.dict.DictStatisticsDTO;
import work.mediway.mdm.biz.entity.biz.SsInterSystems;
import work.mediway.mdm.biz.entity.biz.SsModelInfo;
import work.mediway.mdm.biz.entity.biz.SsServiceLinkSystem;
import work.mediway.mdm.biz.entity.biz.UserBTEventLog;
import work.mediway.mdm.biz.event.DataPushEventEventPublisher;
import work.mediway.mdm.biz.helper.BusinessDatabaseHelper;
import work.mediway.mdm.biz.service.biz.SsInterSystemsService;
import work.mediway.mdm.biz.service.biz.SsModelInfoService;
import work.mediway.mdm.biz.service.biz.SsServiceLinkSystemService;
import work.mediway.mdm.biz.service.biz.TableFieldService;
import work.mediway.mdm.biz.service.biz.UserBTEventLogService;
import work.mediway.mdm.biz.service.dict.CtCodeSystemService;
import work.mediway.mdm.biz.vo.biz.MessageStatisticsVO;
import work.mediway.mdm.biz.vo.dict.DictChangeVO;
import work.mediway.mdm.biz.vo.dict.DictFieldVO;
import work.mediway.mdm.biz.vo.dict.DictFormatTemplateVO;
import work.mediway.mdm.biz.vo.dict.DictStatisticsVO;
import work.mediway.mdm.biz.vo.dict.DictVO;
import work.mediway.mdm.biz.vo.dict.StatisticsDictVO;
import work.mediway.mdm.core.constant.JobConstant;
import work.mediway.mdm.core.constant.MdmConstant;
import work.mediway.mdm.core.constant.SQLConstant;
import work.mediway.mdm.core.entity.TableForeignKey;
import work.mediway.mdm.core.enums.DataFormatEnum;
import work.mediway.mdm.core.enums.StatusEditEnum;
import work.mediway.mdm.core.enums.StatusWhetherEnum;
import work.mediway.mdm.core.exception.DataException;
import work.mediway.mdm.core.helper.BaseDatabaseHelper;
import work.mediway.mdm.core.mapper.CommonMapper;
import work.mediway.mdm.core.page.QueryRequest;
import work.mediway.mdm.core.thread.DimplesTaskExecutor;
import work.mediway.mdm.core.transport.ErrorMsgVO;
import work.mediway.mdm.core.util.CommonUtil;
import work.mediway.mdm.core.util.DUtil;
import work.mediway.mdm.core.util.HttpContextUtil;
import work.mediway.mdm.core.vo.TableVO;

/**
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2021/1/8
 */
@Slf4j
@Transactional(rollbackFor = Exception.class)
@Service
@RequiredArgsConstructor
@SuppressWarnings({"UnnecessaryContinue", "ConstantConditions"})
public class CommonDictServiceImpl implements CommonDictService {

    @Value("${server.port:8080}")
    private String port;

    private final JdbcTemplate jdbcTemplate;
    private final DataSource dataSource;
    private final BusinessDatabaseHelper businessDatabaseHelper;
    private final BaseDatabaseHelper baseDatabaseHelper;
    private final CtCodeSystemService codeSystemService;
    private final UserBTEventLogService userBtEventLogService;
    private final CommonMapper commonMapper;
    private final MessageTypeService messageTypeService;
    private final DataPushEventEventPublisher dataPushEventEventPublisher;
    private final SsInterSystemsService interSystemsService;
    private final SsServiceLinkSystemService serviceLinkSystemService;
    private final TableFieldService tableFieldService;
    private final SsModelInfoService ssModelInfoService;

    @Override
    public Object listDictCodeAndDesc(DictDTO dictDTO, boolean tree) {
        // 查询主键
        List<String> primaryKeys = this.businessDatabaseHelper.getPrimaryKey(dictDTO.getDictType());
        List<String> column = this.businessDatabaseHelper.getColumn(dictDTO.getDictType()).stream().map(DictFieldVO::getFieldCode).collect(Collectors.toList());
        if (StrUtil.isNotBlank(dictDTO.getBusinessFieldCode())) {
            if (!CollUtil.contains(column, "BusinessFieldCode")) {
                return CollUtil.newArrayList();
            }
        }

        StringBuilder sql = new StringBuilder();
        StringBuilder condition = new StringBuilder();
        String code = CommonUtil.allUpperCase(dictDTO.getDictType()) + "_Code";
        if (!CollUtil.contains(column, code)) {
            if (CollUtil.contains(column, "code")) {
                code = "`code`";
            } else if (StrUtil.containsIgnoreCase(StrUtil.join(StrUtil.COMMA, column), "_code")) {
                for (String c : column) {
                    if (StrUtil.containsIgnoreCase(c, "_code")) {
                        code = c;
                        break;
                    } else {
                        code = "''";
                    }
                }
            } else {
                code = "''";
            }
        }

        String desc = CommonUtil.allUpperCase(dictDTO.getDictType()) + "_Desc";
        if (!CollUtil.contains(column, desc)) {
            if (CollUtil.contains(column, "description")) {
                desc = "description";
            } else if (StrUtil.containsIgnoreCase(StrUtil.join(StrUtil.COMMA, column), "_desc")) {
                for (String c : column) {
                    if (StrUtil.containsIgnoreCase(c, "_desc")) {
                        desc = c;
                        break;
                    } else {
                        desc = "''";
                    }
                }
            } else {
                desc = "''";
            }
        }

        String status = CommonUtil.allUpperCase(dictDTO.getDictType()) + "_Status";
        if (!CollUtil.contains(column, status)) {
            if (CollUtil.contains(column, "status")) {
                status = "`status`";
            } else if (StrUtil.containsIgnoreCase(StrUtil.join(StrUtil.COMMA, column), "_status")) {
                for (String c : column) {
                    if (StrUtil.containsIgnoreCase(c, "_status")) {
                        status = c;
                        break;
                    } else {
                        status = "''";
                    }
                }
            } else {
                status = "''";
            }
        }

        sql.append("SELECT ")
                .append(CollUtil.contains(column, "BusinessFieldCode") ? "A.BusinessFieldCode AS businessFieldCode, " : "'' AS businessFieldCode, ")
                .append(CollUtil.contains(column, "businessrowid") ? "A.businessrowid, " : "'' AS businessrowid, ")
                .append(code).append(" AS `code`, ")
                .append(desc).append(" AS `descr`, ")
                .append(status).append(" AS `status`, ")
                .append(CollUtil.contains(column, primaryKeys.get(0)) ? "A." + primaryKeys.get(0) + ", " : "'' AS " + primaryKeys.get(0) + ", ")
                .append(StrUtil.format("{} AS primaryKey", "'" + primaryKeys.get(0) + "'"))
                .append(" FROM ");
        sql.append(dictDTO.getDictType())
                .append(" AS A ");
        if (StrUtil.isNotBlank(dictDTO.getDictParam())) {
            condition.append(" (A.code LIKE '%")
                    .append(dictDTO.getDictParam())
                    .append("%' OR A.description LIKE '%")
                    .append(dictDTO.getDictParam())
                    .append("%') ");
        }
        if (StrUtil.isNotBlank(dictDTO.getBusinessFieldCode())) {
            condition.append(SQLConstant.SQL_CONJ_AND).append(" A.BusinessFieldCode = '")
                    .append(dictDTO.getBusinessFieldCode())
                    .append("'");
        }
        String condit = condition.toString();
        if (StrUtil.startWith(condit, SQLConstant.SQL_CONJ_AND)) {
            condit = StrUtil.removePrefix(condit, SQLConstant.SQL_CONJ_AND);
        }
        if (StrUtil.isNotBlank(condit)) {
            condit = SQLConstant.SQL_CONJ_WHERE + condit;
        }
        String exeSql = sql + condit;
        log.info(MdmConstant.LOG_STR, "查询字典表【" + dictDTO.getDictType() + "】\n" +
                "执行SQL为【" + exeSql + "】");
        List<DictVO> list = jdbcTemplate.query(exeSql, new DictVO());
        list.forEach(origin -> {
            /*if (StrUtil.isNotBlank(origin.getBusinessRowId()) && StrUtil.contains(origin.getBusinessRowId(), StringPool.UNDERSCORE)) {
                origin.setBusinessRowId(StrUtil.splitToArray(origin.getBusinessRowId(), StringPool.UNDERSCORE)[1]);
            }*/
            if (StrUtil.isBlank(origin.getDescr())) {
                origin.setDescr(origin.getCode());
            }
        });
        return list;
    }

    @Override
    public DictStatisticsVO dictChange(DictStatisticsDTO statisticsDTO) {
        DictStatisticsVO vo = new DictStatisticsVO();
        if (StrUtil.isBlank(statisticsDTO.getCurrDate())) {
            statisticsDTO.setCurrDate(DateUtil.today());
        }
        DimplesTaskExecutor<DictStatisticsVO> executor = new DimplesTaskExecutor<>();
        ExecutorCompletionService<DictStatisticsVO> completionService = executor.getCompletionService();
        List<Callable<DictStatisticsVO>> task = CollUtil.newArrayList();
        // 查询昨日字典变化top
        task.add(() -> {
            List<UserBTEventLog> eventLogs = this.userBtEventLogService.list(Wrappers
                    .lambdaQuery(UserBTEventLog.class)
                    .eq(UserBTEventLog::getBtCode, JobConstant.CONST_DICT_CHANGE_KEY)
                    .eq(UserBTEventLog::getLastUpdateDate, DateUtil.formatDate(DateUtil.yesterday())));

            List<DictStatisticsVO.DictChangeTop> dictChangeTops = CollUtil.newArrayList();
            for (UserBTEventLog eventLog : eventLogs) {
                List<StatisticsDictVO> statisticsDictList = JSONUtil.toList(JSONUtil.parseArray(eventLog.getBtDetails()), StatisticsDictVO.class);
                for (StatisticsDictVO statisticsDict : statisticsDictList) {
                    if (DateUtil.isSameDay(DateUtil.offsetDay(DateUtil.parseDate(statisticsDTO.getCurrDate()), -1), DateUtil.parseDate(eventLog.getLastUpdateDate()))) {
                        // 昨日top数据存储
                        DictStatisticsVO.DictChangeTop changeTop = new DictStatisticsVO.DictChangeTop();
                        changeTop.setIncrease(statisticsDict.getIncrease());
                        changeTop.setUpdate(statisticsDict.getUpdate());
                        changeTop.setDictCode(statisticsDict.getDictCode());
                        changeTop.setDictName(statisticsDict.getDictName());
                        changeTop.setTotalChange(statisticsDict.getIncrease() + statisticsDict.getUpdate());
                        dictChangeTops.add(changeTop);
                    }
                }
            }
            // 设置昨日字典数据变化top
            vo.setDictTop(dictChangeTops.stream().sorted(Comparator.comparing(DictStatisticsVO.DictChangeTop::getTotalChange).reversed()).collect(Collectors.toList()));
            return vo;
        });
        // 设置日变化量
        task.add(() -> {
            LambdaQueryWrapper<UserBTEventLog> queryWrapper = Wrappers.lambdaQuery(UserBTEventLog.class).eq(UserBTEventLog::getBtCode, JobConstant.CONST_DICT_CHANGE_KEY);
            if (StrUtil.isNotBlank(statisticsDTO.getStartDate())) {
                queryWrapper.ge(UserBTEventLog::getLastUpdateDate, statisticsDTO.getStartDate());
            } else {
                Date today;
                today = DateUtil.parseDate(statisticsDTO.getCurrDate());
                queryWrapper.ge(UserBTEventLog::getLastUpdateDate, DateUtil.offsetDay(today, -10));
            }
            if (StrUtil.isNotBlank(statisticsDTO.getEndDate())) {
                queryWrapper.le(UserBTEventLog::getLastUpdateDate, statisticsDTO.getEndDate());
            } else {
                queryWrapper.le(UserBTEventLog::getLastUpdateDate, statisticsDTO.getCurrDate());
            }
            List<UserBTEventLog> btEventLogs = this.userBtEventLogService.list(queryWrapper);
            List<DictStatisticsVO.StatisticsVO> change = vo.getChange();
            // 统计列表
            for (UserBTEventLog eventLog : btEventLogs) {
                // 统计日变化
                DictStatisticsVO.StatisticsVO statisticsVO = new DictStatisticsVO.StatisticsVO();
                if (StrUtil.isNotBlank(statisticsDTO.getTableName())) {
                    List<DictChangeVO> vos = JSONUtil.toList(JSONUtil.parseArray(eventLog.getBtDetails()), DictChangeVO.class);
                    for (DictChangeVO v : vos) {
                        if (StrUtil.equalsIgnoreCase(statisticsDTO.getTableName(), v.getDictCode())) {
                            statisticsVO.setIncrease(v.getIncrease());
                            statisticsVO.setUpdate(v.getUpdate());
                            statisticsVO.setDate(eventLog.getLastUpdateDate());
                        }
                    }
                } else {
                    statisticsVO.setIncrease(Integer.valueOf(eventLog.getBtIncrease()));
                    int updateTotal = 0;
                    for (Object item : JSONUtil.parseArray(eventLog.getBtDetails())) {
                        updateTotal += Integer.parseInt(StrUtil.toString(JSONUtil.parseObj(item).get("update")));
                    }
                    statisticsVO.setUpdate(updateTotal);
                    statisticsVO.setDate(eventLog.getLastUpdateDate());
                }
                statisticsVO.setDictTotal(Integer.valueOf(eventLog.getBtTotalNum()));
                change.add(statisticsVO);
            }
            vo.setChange(change);
            return vo;
        });

        // 设置模型数量
        task.add(() -> {
            vo.setModelTotal(this.baseDatabaseHelper.getTable(null).size());
            return vo;
        });
        // 设置字典总数
        task.add(() -> {
            vo.setDictTotal((int) this.codeSystemService.count());
            return vo;
        });
        // 接入系统数量
        task.add(() -> {
            vo.setInterSystemTotal((int) this.interSystemsService.count());
            return vo;
        });
        // 订阅系统数量
        task.add(() -> {
            vo.setSubscribeTotal((int) this.interSystemsService.count());
            return vo;
        });
        // 数据应用
        task.add(() -> {
            // 查询全部
            List<MessageStatisticsVO> messageStatisticsListAll = this.interSystemsService.selectStatisticsMessageList("");
            // 查询昨日
            List<MessageStatisticsVO> messageStatisticsList = this.interSystemsService.selectStatisticsMessageList(DateUtil.formatDate(DateUtil.yesterday()));
            List<String> flagDict = messageStatisticsList.stream().map(MessageStatisticsVO::getTypeName).collect(Collectors.toList());
            // 遍历数据
            for (MessageStatisticsVO messageStatistics : messageStatisticsList) {
                DictStatisticsVO.DictPush dictPush = new DictStatisticsVO.DictPush();
                dictPush.setDictCode(messageStatistics.getTypeName());
                dictPush.setDictName(messageStatistics.getTypeNameDesc());
                for (Integer integer : messageStatistics.getInterSystems().stream().map(SsInterSystems::getCount).collect(Collectors.toList())) {
                    dictPush.setOutputYesterday(dictPush.getOutputYesterday() + integer);
                }
                for (MessageStatisticsVO messageStatisticsAll : messageStatisticsListAll) {
                    if (StrUtil.equalsAnyIgnoreCase(messageStatisticsAll.getTypeName(), messageStatistics.getTypeName())) {
                        List<String> strings = messageStatisticsAll.getInterSystems().stream().map(SsInterSystems::getSsisDesc).collect(Collectors.toList());
                        dictPush.setSubscribeInterSystem(StrUtil.join(",", strings));
                        for (Integer integer : messageStatisticsAll.getInterSystems().stream().map(SsInterSystems::getCount).collect(Collectors.toList())) {
                            dictPush.setTotalOutput(dictPush.getTotalOutput() + integer);
                        }
                    }
                }
                vo.getDataSubscribe().add(dictPush);
            }
            for (MessageStatisticsVO messageStatisticsAll : messageStatisticsListAll) {
                if (!CollUtil.contains(flagDict, messageStatisticsAll.getTypeName())) {
                    DictStatisticsVO.DictPush dictPush = new DictStatisticsVO.DictPush();
                    dictPush.setDictCode(messageStatisticsAll.getTypeName());
                    dictPush.setDictName(messageStatisticsAll.getTypeNameDesc());
                    for (Integer integer : messageStatisticsAll.getInterSystems().stream().map(SsInterSystems::getCount).collect(Collectors.toList())) {
                        dictPush.setTotalOutput(dictPush.getTotalOutput() + integer);
                    }
                    dictPush.setSubscribeInterSystem(StrUtil.join(",", messageStatisticsAll.getInterSystems().stream().map(SsInterSystems::getSsisDesc).collect(Collectors.toList())));
                    vo.getDataSubscribe().add(dictPush);
                }
            }
            return vo;
        });

        task.forEach(completionService::submit);
        for (int i = 0; i < task.size(); i++) {
            try {
                completionService.take().get();
            } catch (Exception e) {
                e.printStackTrace();
                throw new DataException(e.getMessage());
            }
        }
        return vo;
    }

    @Override
    public Page<Map<String, Object>> dictDetailShowOrExport(DictFieldDTO dictDTO, QueryRequest queryRequest, boolean export, boolean allField) {
        Page<Map<String, Object>> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
        // 获取所有的表字段
        List<String> fields;
        if (allField) {
            fields = this.tableFieldService.listDictFieldAll(DictFieldDTO.getInstance().setTableCode(dictDTO.getTableCode()), false).stream().map(DictFieldVO::getFieldCode).collect(Collectors.toList());
        } else {
            fields = this.tableFieldService.listDictField(DictFieldDTO.getInstance().setTableCode(dictDTO.getTableCode()), false).stream().map(DictFieldVO::getFieldCode).collect(Collectors.toList());
        }
        fields = fields.stream().map(item -> "`" + item + "`").collect(Collectors.toList());
        String groupByStr = StrUtil.join(StringPool.COMMA, fields);

        if (CollUtil.isEmpty(fields)) {
            throw new DataException(StrUtil.format("你暂无访问表【tableCode = {}】的权限,请联系管理员分配", dictDTO.getTableCode()));
        }
        // 表外键字段
        List<TableForeignKey> tableForeignKeys = businessDatabaseHelper.getForeignKey(dictDTO.getTableCode());
        // 获取主表字段前缀
        List<String> fieldKeyResult = CollUtil.newArrayList();
        List<String> relResult = CollUtil.newArrayList();

        for (String field : fields) {
            fieldKeyResult.add("A." + field);
        }
        // 组装SQL
        for (int i = 0, len = tableForeignKeys.size(); i < len; i++) {
            TableForeignKey table = tableForeignKeys.get(i);
            String tableAlias = " t" + i;

            List<String> fkTableColumn = this.businessDatabaseHelper.getColumn(table.getFkTableName()).stream().map(DictFieldVO::getFieldCode).collect(Collectors.toList());
            for (String column : fkTableColumn) {
                if (StrUtil.equals("description", column)) {
                    fieldKeyResult.add(tableAlias + StringPool.DOT + column + " AS " + buildForeignDescField(StrUtil.toCamelCase(table.getFkTableName())));
                    break;
                } else if (StrUtil.equals(column, CommonUtil.allUpperCase(table.getFkTableName()) + "_" + "Desc")) {
                    fieldKeyResult.add(tableAlias + StringPool.DOT + column + " AS " + buildForeignDescField(StrUtil.toCamelCase(table.getFkTableName())));
                    break;
                } else if (StrUtil.equals(column, buildForeignDescField(table.getFkColumnName()))) {
                    fieldKeyResult.add(tableAlias + StringPool.DOT + column + " AS " + buildForeignDescField(table.getPkColumnName()));
                    break;
                } else {
                    if (StrUtil.containsAnyIgnoreCase(column, "Name") && !CollUtil.containsAny(fkTableColumn, CollUtil.newArrayList("description", CommonUtil.allUpperCase(table.getFkTableName()) + "_" + "Desc"))) {
                        fieldKeyResult.add(tableAlias + StringPool.DOT + column + " AS " + buildForeignDescField(StrUtil.toCamelCase(table.getFkTableName())));
                    }
                }
            }
            // LEFT JOIN
            relResult.add("LEFT JOIN " + table.getFkTableName() + tableAlias + " ON " +
                    "A." + table.getPkColumnName() + " = " + tableAlias + StringPool.DOT + table.getFkColumnName());
        }

        // 组装数据库查询语句
        StrBuilder sql = new StrBuilder();
        String baseSql = "SELECT " + StrUtil.join(", ", fieldKeyResult) +
                " FROM " + dictDTO.getTableCode() + " A " +
                StrUtil.join(StringPool.SPACE, relResult);
        // 组装条件
        List<String> condi = CollUtil.newArrayList();
        baseSql = buildCondition(dictDTO, fields, baseSql, condi);
        // 组装分页,导出时不分页
        if (export) {
            sql.append(baseSql);
        } else {
            PageUtil.setFirstPageNo(1);
            sql.append(baseSql)
                    .append(" GROUP BY ")
                    .append(groupByStr)
                    .append(" LIMIT ")
                    .append(PageUtil.getStart(queryRequest.getCurrent(), queryRequest.getSize()))
                    .append(",").append(queryRequest.getSize());
        }

        // 查询结果
        // 查询数据总数
        String countSql = "SELECT COUNT(*) FROM " + dictDTO.getTableCode() + " A ";
        if (CollUtil.isNotEmpty(condi)) {
            countSql = countSql + " WHERE " + CollUtil.join(condi, "AND ");
        }
        log.info(MdmConstant.LOG_STR, StrUtil.format("查询字典详细信息的SQL为:【{}】\n查询字典数据总数的SQL为:【{}】\n查询的表为：【{}】\n表字段的前缀为：【{}】", sql, countSql, dictDTO.getTableCode(), ""));
        Integer count = 0;
        if (!export) {
            count = this.jdbcTemplate.queryForObject(countSql, Integer.class);
        }

        List<Map<String, Object>> query = this.jdbcTemplate.queryForList(String.valueOf(sql));

        for (
                Map<String, Object> map : query) {
            // 处理值为NULL字符串
            for (String key : map.keySet()) {
                if (StrUtil.equalsAnyIgnoreCase(StrUtil.NULL, StrUtil.toString(map.get(key)))) {
                    map.put(key, "");
                }
            }
        }
        page.setRecords(query);
        page.setTotal(count);
        page.setPages(PageUtil.totalPage(count, queryRequest.getSize()));
        return page;
    }

    private String buildForeignDescField(String code) {
        return StrUtil.removeSuffixIgnoreCase(code, "Code") + "Desc";
    }

    @Override
    public Page<Map<String, Object>> dictDetailShowOrExportAll(DictFieldDTO dictDTO) {
        return dictDetailShowOrExport(dictDTO, new QueryRequest(1, Integer.MAX_VALUE), false, true);
    }

    private String buildCondition(DictFieldDTO dictDTO, List<String> fields, String baseSql, List<String> condi) {
        if ((StrUtil.isNotBlank(dictDTO.getFieldCode()) && StrUtil.isNotBlank(dictDTO.getFieldValue())) || StrUtil.isNotBlank(dictDTO.getQueryCondi())) {
            baseSql = baseSql + " WHERE ";
            if (StrUtil.isNotBlank(dictDTO.getFieldCode()) && StrUtil.isNotBlank(dictDTO.getFieldValue())) {
                if (!CollUtil.contains(fields, dictDTO.getFieldCode())) {
                    throw new DataException(StrUtil.format("查询参数字段【{}】在表【{}】中不存在", dictDTO.getFieldCode(), dictDTO.getTableCode()));
                }
                condi.add(" A." + dictDTO.getFieldCode() + " LIKE '%" + dictDTO.getFieldValue() + "%'");
            }
            if (StrUtil.isNotBlank(dictDTO.getQueryCondi())) {
                if (StrUtil.containsAnyIgnoreCase(dictDTO.getQueryCondi(), " and ", " or ")) {
                    //添加表别名
                    if (StrUtil.contains(dictDTO.getQueryCondi(), " and ")) {
                        dictDTO.setQueryCondi(StrUtil.replace(dictDTO.getQueryCondi(), " and ", " AND "));
                    }
                    if (StrUtil.contains(dictDTO.getQueryCondi(), " or ")) {
                        dictDTO.setQueryCondi(StrUtil.replace(dictDTO.getQueryCondi(), " or ", " OR "));
                    }
                    if (StrUtil.containsAnyIgnoreCase(dictDTO.getQueryCondi(), " AND ")) {
                        List<String> and = StrUtil.splitTrim(dictDTO.getQueryCondi(), "AND");
                        List<String> andDetail = CollUtil.newArrayList();
                        for (String s : and) {
                            andDetail.add(" A." + StrUtil.removeAll(s, "A.") + " ");
                        }
                        dictDTO.setQueryCondi(StrUtil.join(" AND ", andDetail));
                        condi.add(dictDTO.getQueryCondi());
                    }
                    if (StrUtil.containsAnyIgnoreCase(dictDTO.getQueryCondi(), " OR ")) {
                        List<String> or = StrUtil.splitTrim(dictDTO.getQueryCondi(), "OR");
                        List<String> orDetail = CollUtil.newArrayList();
                        for (String s : or) {
                            orDetail.add(" A." + StrUtil.removeAll(s, "A.") + " ");
                        }
                        dictDTO.setQueryCondi(StrUtil.join(" OR ", orDetail));
                        condi.add(dictDTO.getQueryCondi());
                    }
                } else {
                    condi.add("A." + StrUtil.removeAll(dictDTO.getQueryCondi(), "A."));
                }
            }
            baseSql = baseSql + CollUtil.join(condi, " AND ");
        }
        return baseSql;
    }

    @Override
    public void uploadDictDetail(InputStream inputStream, String tableCode) {
        SimpleJdbcInsert insert = new SimpleJdbcInsert(dataSource).withTableName(tableCode);
        // 获取表字段信息
        Map<String, String> dictField = this.tableFieldService.listDictField(DictFieldDTO.getInstance().setTableCode(tableCode), false)
                .stream().collect(Collectors.toMap(DictFieldVO::getFieldDesc, DictFieldVO::getFieldCode));
        List<TableForeignKey> foreignKey = this.businessDatabaseHelper.getForeignKey(tableCode);
        Map<String, TableForeignKey> foreignMap = MapUtil.newHashMap();
        for (TableForeignKey tableForeignKey : foreignKey) {
            foreignMap.put(tableForeignKey.getPkColumnName(), tableForeignKey);
        }
        ExcelReader reader = ExcelUtil.getReader(inputStream);
        List<Map<String, Object>> readAll = reader.readAll();
        // 获取表前缀
        readAll.forEach(item -> {
            // 存在日期转换问题，自己拼装sql
            Map<String, Object> parameters = MapUtil.newHashMap();
            item.forEach((k, v) -> {
                String value = String.valueOf(v);
                // 时间做特殊处理
                if (DUtil.isDate(value)) {
                    value = DateUtil.formatDate(DateUtil.parseDate(value));
                }
                if (DUtil.isTime(value)) {
                    value = DateUtil.formatTime(DateUtil.parseTime(value));
                }
                parameters.put(dictField.get(k), StrUtil.isBlank(value) ? null : value);
            });
            insert.execute(parameters);
        });
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    @Override
    public ErrorMsgVO saveDictDetail(List<DictDetailDTO> dictDetails, StatusEditEnum opsType) {
        ErrorMsgVO errorMsgVO = new ErrorMsgVO();
        for (DictDetailDTO dictDetail : dictDetails) {
            DictGeneralDTO dictGeneralDTO = new DictGeneralDTO();
            DictGeneralDTO.RequestBean requestBean = new DictGeneralDTO.RequestBean();
            requestBean.setTableCode(dictDetail.getTableCode());
            requestBean.setData(CollUtil.newArrayList(dictDetail.getData()));
            dictGeneralDTO.setRequest(requestBean);
            ErrorMsgVO msgVO = this.saveDictDetail(dictGeneralDTO, "");
            errorMsgVO.addError(msgVO);
        }
        return errorMsgVO;
    }

    @Override
    public ErrorMsgVO saveDictDetail(DictGeneralDTO dictDetail, String xmlData) {
        ErrorMsgVO error = new ErrorMsgVO();

        if (StrUtil.isNotBlank(xmlData)) {
            Gson gson = new Gson();
            dictDetail = gson.fromJson(xmlData, DictGeneralDTO.class);
        }
        DictGeneralDTO.RequestBean request = dictDetail.getRequest();
        if (StrUtil.isBlank(request.getTableCode())) {
            throw new DataException("表【tableCode】不能为空");
        }
        // 判断表代码是否存在
        List<TableVO> table = this.baseDatabaseHelper.getTable(request.getTableCode());
        if (CollUtil.isEmpty(table)) {
            throw new DataException(StrUtil.format("表代码 【tableCode = {}】不存在", request.getTableCode()));
        }
        List<DictFieldVO> column = this.businessDatabaseHelper.getColumn(request.getTableCode());
        List<String> columnCode = column.stream().map(DictFieldVO::getFieldCode).collect(Collectors.toList());
        for (Map<String, Object> data : request.getData()) {
            // 特殊处理
            if (data.containsKey(MdmConstant.FIELD_BUSINESS_FIELD_CODE)
                    && (ObjectUtil.isEmpty(data.get(MdmConstant.FIELD_BUSINESS_FIELD_CODE)) || StrUtil.equals(StrUtil.NULL, StrUtil.toString(data.get(MdmConstant.FIELD_BUSINESS_FIELD_CODE))))) {
                throw new DataException(StrUtil.format("新增/更新字典数据时,业务域代码【{}】不能为空", MdmConstant.FIELD_BUSINESS_FIELD_CODE));
            }
            try {
                // 查询表主键
                List<DictFieldVO> primaryKeys = column
                        .stream().filter(item -> StrUtil.equalsAnyIgnoreCase("Y", item.getPrimaryKey())).collect(Collectors.toList());
                if (CollUtil.isEmpty(primaryKeys)) {
                    throw new DataException(StrUtil.format("表【{}】主键未找到", request.getTableCode()));
                }

                int primaryExistCount = 0;
                for (DictFieldVO primaryKey : primaryKeys) {
                    if (!ObjectUtil.isEmpty(data.get(primaryKey.getFieldCode())) && !StrUtil.isBlank(StrUtil.toString(data.get(primaryKey.getFieldCode())))) {
                        primaryExistCount++;
                    }
                }
                if (!(primaryExistCount == primaryKeys.size())) {
                    // 新增
                    // 先根据传递的所有字段信息判断表中是否已经存在相同数据
                    List<String> where = CollUtil.newArrayList();
                    data.forEach((k, v) -> {
                        if (CollUtil.contains(columnCode, k)) {
                            where.add("`" + k + "` = '" + v + "'");
                        }
                    });
                    String selectRe = SqlBuilder.create(new Wrapper('`', '`'))
                            .select("COUNT(*) AS total")
                            .from(request.getTableCode())
                            .where(StrUtil.join(" AND ", where)).build();
                    try {
                        Number query = SqlExecutor.query(this.baseDatabaseHelper.getLocalConnection(), selectRe, new NumberHandler());
                        if (query.intValue() > 0) {
                            error.setErrorMsg(data, "该数据在表中已存在");
                            break;
                        }
                    } catch (SQLException e) {
                        log.error("通用字典新增时判断数据是否已经存在：" + ExceptionUtil.getExceptionMessage(e));
                        error.setErrorMsg(data, "通用字典新增时判断数据是否已经存在：" + ExceptionUtil.getExceptionMessage(e));
                        break;
                    }

                    for (DictFieldVO primaryKey : primaryKeys) {
                        if (ObjectUtil.isEmpty(data.get(primaryKey.getFieldCode()))) {
                            if (StrUtil.equalsAnyIgnoreCase("VARCHAR", primaryKey.getSqlType())) {
                                data.put(primaryKey.getFieldCode(), IdUtil.getSnowflakeNextIdStr());
                            } else {
                                data.put(primaryKey.getFieldCode(), this.baseDatabaseHelper.buildIncrease(primaryKey.getFieldCode(), request.getTableCode()));
                            }
                        }
                    }
                    saveDetail(request.getTableCode(), data, StatusEditEnum.STATUS_INSERT);
                } else {
                    // 更新
                    updateDetail(request.getTableCode(), data, StatusEditEnum.STATUS_UPDATE);
                }
            } catch (Exception e) {
                error.setErrorMsg(data, e.getMessage());
                e.printStackTrace();
                log.error("数据: {}, 异常信息: {}", data, ExceptionUtil.getRootErrorMessage(e));
            }
        }
        error.setCount(request.getData().size());
        return error;
    }

    private void saveDetail(String tableCode, Map<String, Object> data, StatusEditEnum opsType) {
        List<String> fields = CollUtil.newArrayList();
        List<Object> values = CollUtil.newArrayList();
        List<String> dataKey = CollUtil.newArrayList();
        AtomicBoolean exist = new AtomicBoolean(false);
        // 查询表的所有字段
        List<DictFieldVO> column = this.businessDatabaseHelper.getColumn(tableCode, true);
        List<String> tableColumn = column.stream().map(DictFieldVO::getFieldCode).collect(Collectors.toList());

        data.forEach((k, v) -> dataKey.add(k));

        // 处理code和描述
        buildTableCodeAndDesc(tableCode, data, tableColumn);

        for (DictFieldVO item : column) {
            String fieldCode = item.getFieldCode();
            fields.add("`" + fieldCode + "`");
            if (StrUtil.containsIgnoreCase(fieldCode, MdmConstant.FIELD_CODE_SYSTEM_LIKE)) {
                values.add("'" + tableCode + "'");
                continue;
            }
            // 处理值
            dealValues(data, values, dataKey, exist, item, fieldCode);
        }

        if (!exist.get()) {
            throw new DataException(StrUtil.format("将要保存的参数【{}】在表【{}】中不存在,保存失败", data, tableCode));
        }

        String sql = "INSERT INTO " + tableCode + StringPool.LEFT_BRACKET
                + StrUtil.join(StringPool.COMMA, fields) + StringPool.RIGHT_BRACKET
                + StringPool.SPACE + "VALUES" + StringPool.LEFT_BRACKET
                + StrUtil.join(StringPool.COMMA, values) + StringPool.RIGHT_BRACKET;
        log.info(StrUtil.format("\n====================== 保存字典表数据 =========================\n"
                        + "表代码为：【{}】\n"
                        + "参数为：【{}】\n"
                        + "执行SQL为：【{}】\n"
                        + "============================================================="
                , tableCode, data, sql));
        this.commonMapper.saveItems(sql);
    }

    private void buildTableCodeAndDesc(String tableCode, Map<String, Object> data, List<String> tableColumn) {
        String code = CommonUtil.allUpperCase(tableCode) + "_Code";
        String desc = CommonUtil.allUpperCase(tableCode) + "_Desc";
        if (ObjectUtil.isNotEmpty(data.get("code")) && !ObjectUtil.isNotEmpty(data.get(code))) {
            data.put("code", data.get("code"));
            data.put("description", data.get("description"));
            if (CollUtil.contains(tableColumn, code)) {
                data.put(code, data.get(code));
            }
            if (CollUtil.contains(tableColumn, desc)) {
                data.put(desc, data.get(desc));
            }
        } else if (!ObjectUtil.isNotEmpty(data.get("code")) && ObjectUtil.isNotEmpty(data.get(code))) {
            data.put(code, data.get(code));
            data.put(desc, data.get(desc));
            if (CollUtil.contains(tableColumn, "code")) {
                data.put("code", data.get("code"));
            }
            if (CollUtil.contains(tableColumn, "description")) {
                data.put("description", data.get("description"));
            }
        }
    }

    private void dealValues(Map<String, Object> data, List<Object> values, List<String> dataKey, AtomicBoolean exist, DictFieldVO item, String fieldCode) {
        if (CollUtil.contains(dataKey, fieldCode)) {
            exist.set(true);
            // 处理外键
            if (StrUtil.isNotBlank(item.getFkColumnName())) {
                if (StrUtil.equals(StrUtil.NULL, StrUtil.toString(data.get(fieldCode))) || ObjectUtil.isEmpty(data.get(fieldCode))) {
                    values.add(null);
                } else {
                    values.add("'" + data.get(fieldCode) + "'");
                }
            } else if (data.get(fieldCode) instanceof Long || data.get(fieldCode) instanceof Integer) {
                // 处理数字类型
                values.add(data.get(fieldCode));
            } else if (StrUtil.containsIgnoreCase(item.getSqlType(), MdmConstant.FIELD_DATE_LIKE) || StrUtil.containsIgnoreCase(item.getSqlType(), MdmConstant.FIELD_TIME_LIKE)) {
                // 处理日期字段
                if (ObjectUtil.isNotEmpty(data.get(fieldCode)) && !StrUtil.equalsAnyIgnoreCase(StrUtil.toString(data.get(fieldCode)), StrUtil.NULL)) {
                    if (StrUtil.containsIgnoreCase(item.getSqlType(), MdmConstant.FIELD_DATE_LIKE)) {
                        values.add("'" + StrUtil.splitToArray(DateUtil.formatDateTime(DateUtil.parse(StrUtil.toString(data.get(fieldCode)))), StringPool.SPACE)[0] + "'");
                    } else if (StrUtil.containsIgnoreCase(item.getSqlType(), MdmConstant.FIELD_TIME_LIKE)) {
                        values.add("'" + StrUtil.splitToArray(DateUtil.formatDateTime(DateUtil.parse(StrUtil.toString(data.get(fieldCode)))), StringPool.SPACE)[1] + "'");
                    }
                } else {
                    if (item.getRequired()) {
                        if (StrUtil.equalsAnyIgnoreCase(item.getSqlType(), MdmConstant.FIELD_DATE_LIKE)) {
                            values.add("'" + DateUtil.today() + "'");
                        } else if (StrUtil.equalsAnyIgnoreCase(item.getSqlType(), MdmConstant.FIELD_TIME_LIKE)) {
                            values.add("'" + DUtil.splitNow()[1] + "'");
                        } else if (StrUtil.equalsAnyIgnoreCase(item.getSqlType(), "datetime") || StrUtil.equalsAnyIgnoreCase(item.getSqlType(), "timestamp")) {
                            values.add("'" + DateUtil.now() + "'");
                        } else {
                            values.add("'" + DateUtil.now() + "'");
                        }
                    } else {
                        values.add(null);
                    }
                }
            } else {
                if (StrUtil.equals(StrUtil.NULL, StrUtil.toString(data.get(fieldCode)))) {
                    if (item.getRequired()) {
                        values.add("''");
                    } else {
                        values.add(null);
                    }
                } else {
                    values.add("'" + data.get(fieldCode) + "'");
                }
            }
        } else {
            // 处理日期字段
            if (StrUtil.containsIgnoreCase(item.getSqlType(), MdmConstant.FIELD_DATE_LIKE) || StrUtil.containsIgnoreCase(item.getSqlType(), MdmConstant.FIELD_TIME_LIKE)) {
                if (StrUtil.containsIgnoreCase(item.getSqlType(), MdmConstant.FIELD_DATE_LIKE) && !StrUtil.containsIgnoreCase(item.getFieldCode(), MdmConstant.FIELD_END_DATE_LIKE)) {
                    values.add("'" + DUtil.splitNow()[0] + "'");
                } else if (StrUtil.containsIgnoreCase(item.getSqlType(), MdmConstant.FIELD_TIME_LIKE)) {
                    values.add("'" + DUtil.splitNow()[1] + "'");
                } else {
                    if (item.getRequired()) {
                        values.add("''");
                    } else {
                        values.add(null);
                    }
                }
            } else if (StrUtil.containsIgnoreCase(item.getFieldCode(), MdmConstant.FIELD_USER_CODE_LIKE)) {
                values.add("'" + SecurityUtils.getLoginName() + "'");
            } else {
                // 处理必填字段
                if (item.getRequired()) {
                    if (StrUtil.equalsAnyIgnoreCase(item.getFieldCode(), "id")) {
                        values.add(null);
                    } else {
                        values.add("''");
                    }
                } else {
                    values.add(null);
                }
            }
        }
    }

    private void updateDetail(String tableCode, Map<String, Object> data, StatusEditEnum opsType) {
        // 查询表的所有字段
        List<DictFieldVO> column = this.businessDatabaseHelper.getColumn(tableCode, true);
        Map<String, DictFieldVO> fieldMap = column.stream().collect(Collectors.toMap(DictFieldVO::getFieldCode, vo -> vo));
        List<String> primarys = column.stream().filter(item
                -> StrUtil.equalsAnyIgnoreCase(item.getPrimaryKey(), StatusWhetherEnum.STATUS_Y.getStatusCode())).map(DictFieldVO::getFieldCode).collect(Collectors.toList());
        if (CollUtil.isEmpty(primarys)) {
            throw new DataException(StrUtil.format("表 = {} 不存在主键，不能更新", tableCode));
        }

        List<String> where = CollUtil.newArrayList();
        for (String parimary : primarys) {
            where.add(" `" + parimary + "` = '" + data.get(parimary) + "' ");
        }

        // 查询是否真的不存在该主键值数据
        String dataSql = "SELECT * FROM " + tableCode + " WHERE " + StrUtil.join("AND", where);
        try {
            Map<String, Object> dbData = jdbcTemplate.queryForMap(dataSql);
        } catch (Exception e) {
            saveDetail(tableCode, data, StatusEditEnum.STATUS_INSERT);
            return;
        }

        List<String> update = CollUtil.newArrayList();
        for (String key : data.keySet()) {
            DictFieldVO item = fieldMap.get(key);
            if (ObjectUtil.isNotEmpty(item)) {
                if (!CollUtil.contains(primarys, item.getFieldCode())) {
                    if (ObjectUtil.isEmpty(data.get(key))) {
                        continue;
                    } else if (data.get(key) instanceof Long || data.get(key) instanceof Integer) {
                        update.add("`" + key + "`" + " = " + data.get(key));
                    } else {
                        update.add("`" + key + "`" + " = '" + data.get(key) + "'");
                    }
                }
            }
        }
        String sql = "UPDATE " + tableCode + " SET "
                + StrUtil.join(StringPool.COMMA, update)
                + " WHERE " + StrUtil.join("AND", where);
        log.info(StrUtil.format("\n====================== 更新字典表数据 =========================\n"
                        + "表代码为：【{}】\n"
                        + "参数为：【{}】\n"
                        + "执行SQL为：【{}】\n"
                        + "============================================================="
                , tableCode, data, sql));
        this.commonMapper.saveItems(sql);
    }

    @Override
    public ErrorMsgVO removeDict(DictGeneralDeleteDTO dictGeneralDeleteDTO) {
        ErrorMsgVO error = new ErrorMsgVO();
        String table = dictGeneralDeleteDTO.getTable();
        // 判断表是否存在
        List<String> tables = this.baseDatabaseHelper.getTable(table).stream().map(TableVO::getTableCode).collect(Collectors.toList());
        if (!CollUtil.contains(tables, table)) {
            throw new DataException(StrUtil.format("表 【table = {}】不存在", table));
        }
        // 查询表主键字段
        List<String> primaryKeyFromDb = this.businessDatabaseHelper.getPrimaryKey(table);

        List<Map<String, Object>> primaryVals = dictGeneralDeleteDTO.getPrimaryVals();
        // 过滤
        List<Map<String, Object>> tmp = CollUtil.newArrayList();
        for (String pk : primaryKeyFromDb) {
            Map<String, Object> t = MapUtil.newHashMap();
            for (Map<String, Object> primaryVal : primaryVals) {
                if (ObjectUtil.isNotEmpty(primaryVal.get(pk))) {
                    t.put(pk, primaryVal.get(pk));
                }
            }
            tmp.add(t);
        }

        Set<String> primaryKeySet = tmp.get(0).keySet();
        if (!CollUtil.isEqualList(primaryKeyFromDb.stream().sorted().collect(Collectors.toList()), primaryKeySet.stream().sorted().collect(Collectors.toList()))) {
            throw new DataException(StrUtil.format("需传输的主键字段为: {}, 请检查是否完整", primaryKeyFromDb));
        }

        for (Map<String, Object> primaryVal : tmp) {
            List<String> where = CollUtil.newArrayList();
            primaryVal.forEach((k, v) -> where.add(" `" + k + "` = '" + v + "' "));
            String sql = "DELETE FROM " + table + " WHERE " + StrUtil.join(" AND ", where);
            try {
                this.commonMapper.updateItems(sql);
            } catch (Exception e) {
                log.error(ExceptionUtil.getExceptionMessage(e), e);
                error.setErrorMsg(primaryVal, StrUtil.format("删除失败,错误信息：【{}】", e.getMessage()));
            }
        }
        error.setCount(primaryVals.size());
        return error;
    }

    @Override
    public ErrorMsgVO importDict(ExcelReader excelReader) {
        String table = excelReader.getSheetNames().get(0);
        List<TableVO> tableVOList = this.baseDatabaseHelper.getTable(table);
        if (CollUtil.isEmpty(tableVOList)) {
            throw new DataException(StrUtil.format("table = {}不存在", table));
        }
        List<String> tableField = this.businessDatabaseHelper.getColumn(table).stream().map(DictFieldVO::getFieldCode).collect(Collectors.toList());
        List<Map<String, Object>> data = excelReader.readAll();
        List<DictDetailDTO> insertData = CollUtil.newArrayList();

        data.forEach(item -> {
            DictDetailDTO detailDTO = new DictDetailDTO();
            detailDTO.setTableCode(table);
            Map<String, Object> detail = MapUtil.newHashMap();
            item.forEach((k, v) -> {
                String[] field = StrUtil.splitToArray(k, StringPool.DASH);
                if (field.length > 1 && CollUtil.contains(tableField, field[1])) {
                    detail.put(field[1], StrUtil.toString(v));
                }
            });
            detailDTO.setData(detail);
            insertData.add(detailDTO);
        });
        return this.saveDictDetail(insertData, null);
    }

    @Override
    public void pushDict(DictPushBO dictPushBO) {
        Assert.notBlank(dictPushBO.getTableCode());
        dictPushBO.setTableCode(StrUtil.removePrefixIgnoreCase(dictPushBO.getTableCode(), MdmConstant.SCHEMA_NAME_));
        SsModelInfo ssModelInfo = new SsModelInfo();
        ssModelInfo.setModelCode(dictPushBO.getTableCode());
        Page<SsModelInfo> modelInfo = this.ssModelInfoService.getByModelInfo(ssModelInfo, new QueryRequest());
        if (CollUtil.isEmpty(modelInfo.getRecords())) {
            log.info("数据服务管理中不存在该 tableCode = {}", dictPushBO.getTableCode());
            return;
        }
        MessageType messageType = new MessageType();
        messageType.setTypeName(dictPushBO.getTableCode());
        List<MessageType> messageTypes = messageTypeService.selectAllMessageTypeList(messageType);
        if (CollUtil.isEmpty(messageTypes)) {
            log.info("参考数据：tableCode = {} 未绑定任何消息", dictPushBO.getTableCode());
            return;
        }
        // 查询需要转发数据
        String condition;
        List<String> conditions = CollUtil.newArrayList();
        // 必需为发布状态的数据才给推送
        if (StrUtil.isNotBlank(dictPushBO.getQueryCondi())) {
            conditions.add(dictPushBO.getQueryCondi());
        }
        if (MapUtil.isNotEmpty(dictPushBO.getParam())) {
            dictPushBO.getParam().forEach((k, v) -> conditions.add(" `" + k + "` = '" + v + "'"));
        }
        if (StrUtil.isNotBlank(dictPushBO.getPushData())) {
            if (!JSONUtil.isJsonArray(dictPushBO.getPushData())) {
                dictPushBO.setPushData(JSONUtil.toJsonStr(new JSONArray(dictPushBO.getPushData())));
            }
            for (Object data : JSONUtil.parseArray(dictPushBO.getPushData())) {
                JSONObject dataJson = JSONUtil.parseObj(data);
                Object release = dataJson.get("release");
                if (!(ObjectUtil.isNotEmpty(release) && StrUtil.equalsAnyIgnoreCase(StrUtil.toString(release), StatusWhetherEnum.STATUS_Y.getStatusCode()))) {
                    return;
                }
            }
        } else {
            List<String> column = this.businessDatabaseHelper.getColumn(dictPushBO.getTableCode()).stream().map(DictFieldVO::getFieldCode).collect(Collectors.toList());
            if (CollUtil.contains(column, "release")) {
                conditions.add("`release` = 'Y'");
            } else if (CollUtil.contains(column, "releases")) {
                conditions.add("`releases` = 'Y'");
            } else {
                for (String col : column) {
                    if (StrUtil.containsIgnoreCase(col, "_Activity")) {
                        conditions.add("`" + col + "` = 'Y'");
                        break;
                    }
                }
                // 填充位置，防止下方判断为空不查询数据库
                if (CollUtil.isEmpty(conditions)) {
                    conditions.add("`1 = 1");
                }
            }
        }
        if (CollUtil.isNotEmpty(conditions)) {
            condition = StrUtil.join(" AND ", conditions);
            Page<Map<String, Object>> page = dictDetailShowOrExportAll(DictFieldDTO.getInstance().setTableCode(dictPushBO.getTableCode()).setQueryCondi(condition));
            dictPushBO.setPushData(JSONUtil.toJsonStr(page.getRecords()));
        }
        // 构建数据推送
        if (StrUtil.isEmpty(dictPushBO.getPushData())) {
            return;
        }
        if (CollUtil.isEmpty(dictPushBO.getInterSystemCode())) {
            // 推送给所有服务
            for (MessageType type : messageTypes) {
                MessageEntity messageEntity = new MessageEntity();
                messageEntity.setTypeId(type.getTypeId());
                messageEntity.setEntityBody(StrUtil.format(MdmConstant.DICT_GENERAL_STYLE, dictPushBO.getPushData(), dictPushBO.getTableCode()));
                dataPushEventEventPublisher.publishEvent(messageEntity);
            }
        } else {
            // 根据系统去查询对应的绑定消息
            List<SsInterSystems> systems = this.interSystemsService.list(Wrappers.lambdaQuery(SsInterSystems.class).in(SsInterSystems::getSsisCode, dictPushBO.getInterSystemCode()));
            List<SsServiceLinkSystem> serviceLinkSystems = this.serviceLinkSystemService.list(Wrappers.lambdaQuery(SsServiceLinkSystem.class)
                    .in(SsServiceLinkSystem::getSsslsSystemId, systems.stream().map(SsInterSystems::getId).collect(Collectors.toList())));
            // 根据传入系统过滤后需要推送的服务，如果根据字典查询结果中的订阅服务相等，则推送
            List<Long> serviceSystemIds = serviceLinkSystems.stream().map(SsServiceLinkSystem::getSsslsServiceId).collect(Collectors.toList());
            for (MessageType type : messageTypes) {
                for (String serviceId : StrUtil.split(type.getTypeSubscribe(), ",")) {
                    if (CollUtil.contains(serviceSystemIds, Long.parseLong(serviceId))) {
                        // 根据服务过滤
                        MessageEntity messageEntity = new MessageEntity();
                        messageEntity.setTypeId(type.getTypeId());
                        messageEntity.setEntityBody(StrUtil.format(MdmConstant.DICT_GENERAL_STYLE, dictPushBO.getPushData(), dictPushBO.getTableCode()));
                        dataPushEventEventPublisher.publishEvent(messageEntity);
                    }
                }
            }
        }
    }

    @Override
    public DictFormatTemplateVO buildDictTemplate(String table, DataFormatEnum format) {
        DictFormatTemplateVO dictFormatTemplate = new DictFormatTemplateVO();
        // ======================================= 数据存储服务 ======================================= //
        DictFormatTemplateVO.Format templateInput = dictFormatTemplate.getInput();
        // 构建数据请求格式
        List<DictFieldVO> column = businessDatabaseHelper.getColumn(table);
        column = column.stream().filter(item -> !StrUtil.equalsAnyIgnoreCase("YES", item.getIsAutoIncrement())).collect(Collectors.toList());
        if (format == DataFormatEnum.XML) {
            org.json.JSONObject request = new org.json.JSONObject();
            org.json.JSONObject result = new org.json.JSONObject();

            org.json.JSONObject data = new org.json.JSONObject();
            for (DictFieldVO dictFieldVO : column) {
                data.put(dictFieldVO.getFieldCode(), dictFieldVO.getFieldDesc());
            }
            result.put("Data", data);
            result.put("TableCode", table);
            request.put("Request", result);
            templateInput.setDataFormat(XML.toString(request));
            templateInput.setHeader(ContentType.FORM_URLENCODED.getValue());
            templateInput.setParamType("form");
            Map<String, Object> paramMap = MapUtil.newHashMap();
            paramMap.put("xmlData", "");
            templateInput.setParam(paramMap);
        } else {
            JSONObject request = new JSONObject();
            JSONObject result = new JSONObject();
            JSONArray data = new JSONArray();
            JSONObject detail = new JSONObject();
            for (DictFieldVO dictFieldVO : column) {
                detail.set(dictFieldVO.getFieldCode(), dictFieldVO.getFieldDesc());
            }
            data.add(detail);
            result.set("data", data);
            result.set("tableCode", table);
            request.set("request", result);
            templateInput.setDataFormat(request);
            templateInput.setHeader(ContentType.JSON.getValue());
            templateInput.setParamType("body");
        }
        // 请求方法
        templateInput.setMethod(Method.POST.name());
        // 请求地址
        templateInput.setUrl(StrUtil.format("http://{}:{}/{}", HttpContextUtil.getHostIp(), port, "dict/general"));
        templateInput.setSuccess(JSONUtil.parse(BaseResponse.success()));
        templateInput.setType("HTTP");

        // ======================================= 数据查询服务 ======================================= //
        DictFormatTemplateVO.Format templateOutput = dictFormatTemplate.getOutput();

        // 请求方法
        templateOutput.setMethod(Method.GET.name());
        templateOutput.setType("HTTP");
        templateOutput.setUrl(StrUtil.format("http://{}:{}/{}", HttpContextUtil.getHostIp(), port, "dict/general"));
        templateOutput.setHeader(ContentType.FORM_URLENCODED.getValue());
        templateOutput.setParamType("form");
        Map<String, Object> paramMap = MapUtil.newHashMap();
        paramMap.put("tableCode", table);
        paramMap.put("pageNumber", "1");
        paramMap.put("pageSize", "10");
        templateOutput.setParam(paramMap);
        Map<String, Object> map = MapUtil.newHashMap();
        column.forEach(item -> map.put(item.getFieldCode(), item.getFieldDesc()));
        List<Map<String, Object>> success = CollUtil.newArrayList();
        success.add(map);
        templateOutput.setSuccess(JSONUtil.parse(BaseResponse.success(success)));
        return dictFormatTemplate;
    }
}

